Google Maps provides information about traffic conditions across an area. This package provides functions to produce georeferenced rasters from live Google Maps traffic information. Providing Google traffic information in a georeferenced data format facilitates analysis of traffic information (e.g., spatially merging traffic information with other data sources).
The below image shows an example raster produced using the package showing traffic within Washington, DC.
Pixel values in rasters are derived from Google traffic colors and can be one of four values:
| Google Traffic Color | Description | Raster Value |
|---|---|---|
| Green | No traffic delays | 1 |
| Orange | Medium traffic | 2 |
| Red | High traffic | 3 |
| Dark Red | Heavy traffic | 4 |
The package provides function to query Google traffic data around a location, within a polygon, or using a grid. The main functions are the following:
The package is available via github and can be installed using
devtools.
# install.packages("devtools")
devtools::install_github("dime-worldbank/googletraffic")
Querying Google traffic information requires a Google API key with the Maps Javascript API enabled. To create a Google API key, follow these instructions.
The below code should be run before running the following examples. We load packages, set the Google API key, and define a palette used for visualizing traffic data in leaflet.
## Load Google Traffic package
library(googletraffic)
## Load additional packages for working with and visualizing data
library(leaflet)
library(leaflet.extras)
library(leaflet.providers)
library(scales)
library(mapview)
library(raster)
library(tidyverse)
## Set Google API Key
google_key <- "GOOGLE-API-KEY-HERE"
## Define Leaflet Palette and Legend
traffic_pal <- colorNumeric(c("green", "orange", "red", "#660000"),
1:4,
na.color = "transparent")
The following are key parameters relevant across functions for querying Google Traffic data.
height and
width parameters define the height and width of the raster
in terms of pixels. The kilometer height/width of pixels depends
primarily on the zoom level (larger zoom
levels correspond to the height and width
having a smaller kilometer distance).Large height/width and delay time: Google traffic
data takes time to render on a map, and larger height and
width values require more time needed for data to render.
The functions automatically scale the delay time depending on the
height and width values set, but the delay
time can also be manually set using the webshot_delay
parameter. Note that traffic data may fail to render for very large
height and width values, no matter the
webshot_delay set (we find that the function works well
with a height/width of 2000 or less).
The gt_make_raster() function produces a raster, using a
centroid location and a height/width around the centroid to specify the
location to query traffic information. The below example queries traffic
for lower Manhattan, NYC.
## Make raster
r <- gt_make_raster(location = c(40.712778, -74.006111),
height = 1000,
width = 1000,
zoom = 16,
google_key = google_key)
#> Pausing for 5 seconds to allow traffic data to render
## Map raster
leaflet(width = "100%") %>%
addProviderTiles("Esri.WorldGrayCanvas") %>%
addRasterImage(r, colors = traffic_pal, opacity = 1)
By using a smaller zoom, we can capture a larger area;
however, the pixels are more coarse.
## Make raster
r <- gt_make_raster(location = c(41.384900, -78.891302),
height = 1000,
width = 1000,
zoom = 7,
google_key = google_key)
#> Pausing for 5 seconds to allow traffic data to render
## Map raster
leaflet(width = "100%") %>%
addProviderTiles("Esri.WorldGrayCanvas") %>%
addRasterImage(r, colors = traffic_pal, opacity = 1) %>%
setView(lat = 41.384900, lng = -78.891302, zoom = 6)
The above example showed querying traffic information for lower
Manhattan. Here, we show querying traffic information for all of
Manhattan while still using a relatively high zoom level (that allows
capturing traffic on smaller streets). The
gt_make_raster_from_polygon() accepts a polygon as an
input; if needed, multiple API queries are made to query traffic for the
full polygon. We still specify the height and
width, which determines the height and width used for a
single API query. Large height and width
values will result in fewer Google queries, while smaller
height and width values will require more
queries to cover the same spatial area; traffic data will fail to render
if too large of height and width values are
set.
## Grab polygon of Manhattan
us_sp <- getData('GADM', country='USA', level=2)
ny_sp <- us_sp[us_sp$NAME_2 %in% "New York",]
## Make raster
r <- gt_make_raster_from_polygon(polygon = ny_sp,
height = 2000,
width = 2000,
zoom = 15,
google_key = google_key)
## Map raster
leaflet(width = "100%") %>%
addProviderTiles("Esri.WorldGrayCanvas") %>%
addRasterImage(r, colors = traffic_pal, opacity = 1)
gt_make_raster_from_polygon() creates a grid that covers
a polygon, creates a traffic raster for each grid, and merges the
rasters together. Some may prefer to first create and see the grid, then
create a traffic raster using this grid. For example, one could (1)
create a grid that covers a polygon then (2) remove certain grid tiles
that cover areas that may not be of interest. The
gt_make_grid() and gt_make_raster_from_grid()
functions facilitate this process; gt_make_grid() creates a
grid, then gt_make_raster_from_grid() uses a grid as an
input to create a traffic raster.
First, we create a grid using gt_make_grid().
grid_df <- gt_make_grid(polygon = ny_sp,
height = 2000,
width = 2000,
zoom = 15)
leaflet(width = "100%") %>%
addTiles() %>%
addPolygons(data = grid_df, popup = ~as.character(id))
We notice that the tile in the bottom left corner just covers water and some land outside of Manhattan. To reduce the number of API queries we need to make, we can remove this tile.
grid_clean_df <- grid_df[-5,]
leaflet(width = "100%") %>%
addTiles() %>%
addPolygons(data = grid_clean_df)
Second, we use the grid to make a traffic raster using
gt_make_raster_from_grid().
## Make raster
r <- gt_make_raster_from_grid(grid_param_df = grid_clean_df,
google_key = google_key)
## Map raster
leaflet(width = "100%") %>%
addProviderTiles("Esri.WorldGrayCanvas") %>%
addRasterImage(r, colors = traffic_pal, opacity = 1)
To make a google traffic raster, the functions first makes a temporary png file then converts the png file to a raster—where only the raster is outputted. Some workflows may require separating the processes, where a PNG file would first be created, then the PNG file would be converted to a raster.
To support these workflows, the package provides the:
gt_make_png() function which creates a
PNG file with traffic datagt_load_png_as_traffic_raster()
function which converts a PNG file into a spatially-referenced traffic
rasterThe below example illutrates the process.
#### Make png
# The function does not output anything in R; it saves a png file, specified
# using the "out_filename" parameter
gt_make_png(location = c(40.712778, -74.006111),
height = 1000,
width = 1000,
zoom = 16,
out_filename = "google_traffic.png",
google_key = google_key)
#### Convert png to raster
# We now convert the "google_traffic.png" created above into a raster. Because
# the png is not spatially referenced, we need to enter the same
r <- gt_load_png_as_traffic_raster(filename = "google_traffic.png",
location = c(40.712778, -74.006111),
height = 1000,
width = 1000,
zoom = 16)
We can also use this process when querying traffic data for a larger study area that requires making multiple API calls. The below example illustrates creating multiple pngs from a grid.
#### Make grid
# We first make a grid, which contains all the parameters needed to make a png then
# the raster
grid_df <- gt_make_grid(polygon = ny_sp,
height = 2000,
width = 2000,
zoom = 15)
print(grid_df)
#> Simple feature collection with 6 features and 6 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: -74.10988 ymin: 40.68462 xmax: -73.85324 ymax: 40.87875
#> Geodetic CRS: WGS 84
#> longitude latitude id height width zoom geometry
#> 1 -73.98156 40.84630 1 2000 2000 15 POLYGON ((-74.02448 40.8138...
#> 2 -73.89616 40.84630 2 2000 2000 15 POLYGON ((-73.93907 40.8138...
#> 3 -73.98156 40.78173 3 2000 2000 15 POLYGON ((-74.02448 40.7492...
#> 4 -73.89616 40.78173 4 2000 2000 15 POLYGON ((-73.93907 40.7492...
#> 5 -74.06696 40.71715 5 2000 2000 15 POLYGON ((-74.10988 40.6846...
#> 6 -73.98156 40.71715 6 2000 2000 15 POLYGON ((-74.02448 40.6846...
#### Make PNGs from grid
# Exports PNGs
for(i in 1:nrow(grid_df)){
grid_i_df <- grid_df[i,]
gt_make_png(location = c(grid_i_df$latitude, grid_i_df$longitude),
height = grid_i_df$height,
width = grid_i_df$width,
zoom = grid_i_df$zoom,
out_filename = paste0(i, "_google_traffic.png"),
google_key = google_key)
}
#### Convert PNGs to rasters
# Here we make a list of rasters
r_list <- lapply(1 in 1:nrow(grid_df)){
grid_i_df <- grid_df[i,]
gt_load_png_as_traffic_raster(filename = paste0(i, "_google_traffic.png"),
location = c(grid_i_df$latitude, grid_i_df$longitude),
height = grid_i_df$height,
width = grid_i_df$width,
zoom = grid_i_df$zoom)
}
#### Mosaic rasters together
# To mosaic the rasters together, the mosaic() function from the raster package
# requires that rasters have the same origin and resolution. The above rasters will
# not have the same orgin, and the resolutions will be slightly different. The
# gt_mosaic() function allows mosaicing rasters with different origins and resolutions.
r <- gt_mosaic(r_list)